/*****************************************************************************
 *  CommLayerLib - NetworkLayer.java
 *  Copyright (C) 2012  Matteo Piscitelli
 *  E-mail: matteo@picciux.it
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *  For further info, check http://code.google.com/p/java-comm-layer/
 *
 *  SVN: $Id: NetworkLayer.java 41 2012-10-11 16:35:35Z picciux@gmail.com $
 *  
 *****************************************************************************/

package it.picciux.commlayer.net;

import java.io.IOException;

import it.picciux.commlayer.CommLayer;
import it.picciux.commlayer.CommLayerException;
import it.picciux.commlayer.ConfigValue;
import it.picciux.commlayer.DataWriter;

public abstract class NetworkLayer extends CommLayer {
	public class Settings extends CommLayer.Settings {
		private String host;
		private int port;
		
		public boolean setConfigValue(ConfigValue v) {
			if (v.getKey().equalsIgnoreCase("host"))
				host = v.getValueString();
			else if (v.getKey().equalsIgnoreCase("port"))
				port = v.getValueInt();
			else if (v.getKey().equalsIgnoreCase("url")) {
				setUrl(v.getValueString());
			} else
				return false;

			return true;
		}

		public ConfigValue getNextConfig() {
			ConfigValue ret = null;
			
			if (fieldIndex == 0)
				ret = new ConfigValue("host", host);
			else if (fieldIndex == 1)
				ret = new ConfigValue("port", port);
			else
				return null;
			
			fieldIndex++;
			return ret;
		}

		public CommLayer.Settings clone() {
			Settings s = new Settings();
			s.host = new String(host);
			s.port = port;
			return s;
		}

		/**
		 * @return the host
		 */
		public String getHost() {
			return host;
		}

		/**
		 * @param host the host to set
		 */
		public void setHost(String host) {
			this.host = host;
		}

		/**
		 * @return the port
		 */
		public int getPort() {
			return port;
		}

		/**
		 * @param port the port to set
		 */
		public void setPort(int port) {
			this.port = port;
		}
		
		public String getUrl() {
			return host + ":" + port;
		}
		
		public void setUrl(String url) {
			int i = url.indexOf(':');
			if (i == -1) 
				host = url;
			else {
				host = url.substring(0, i);
				port = Integer.parseInt(url.substring(i+1));
			}
		}
		
	}
	
	protected TCPClient client = null;
	
	public static final int UNKNOWN_HOST		= (NETWORK * 100) + 0;
	public static final int MALFORMED_URL		= (NETWORK * 100) + 1;
	
	public NetworkLayer() {
		super();
		settings = new Settings();
		
		setTCPClient();
		
	}

	public boolean canScan() {
		return false;
	}

	public int getType() {
		return CommLayer.NETWORK;
	}

	public it.picciux.commlayer.CommLayer.Settings getSettings() {
		return settings;
	}
	
	protected abstract void setTCPClient();
	protected abstract DataReader newDataReader();
	protected abstract DataWriter newDataWriter();
	
	protected void tryConnection() throws CommLayerException {
		client.connect(((Settings) getSettings()).getUrl());
		try {
			in = client.getInputStream();
			out = client.getOutputStream();
		} catch (IOException e) {
			throw new CommLayerException(e.getMessage(), CONNECTION_ERROR);
		}
		
		if (notifyOnDataAvailable) 
			dataReader = newDataReader();
		
		if (writeOnSeparateThread) 
			dataWriter = newDataWriter();

	}

	protected void doDisconnect() {
		client.disconnect();
	}

}
